﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
using Mitosoft.Definitions.Services;

namespace Mitosoft.Definitions.ViewModels
{
  /// <summary>
  /// View model used to select a directory.
  /// </summary>
  public class DirectorySelectionViewModel : BaseViewModel
  {
    #region events

    #endregion

    #region fields

    /// <summary>
    /// Represents <see cref="SelectDirectoryCommand"/>
    /// </summary>
    protected ICommand _selectDirectoryCommand;
    
    /// <summary>
    /// Represents <see cref="ShowDirectories"/>
    /// </summary>
    protected bool _showDirectories;

    /// <summary>
    /// Represents <see cref="DirectoryService"/>
    /// </summary>
    protected IDirectoryService _directoryService;

    /// <summary>
    /// Represents <see cref="SelectedDirectory"/>
    /// </summary>
    protected IOViewModel _selectedDirectory;

    #endregion

    #region constructors

    /// <summary>
    /// Creates a new <see cref="DirectorySelectionViewModel"/> instance.
    /// </summary>
    // ReSharper disable once EmptyConstructor
    public DirectorySelectionViewModel()
    {
      // Intentionally left blank.
    }

    /// <summary>
    /// Destructor. Will run only if Dispose has not been called.
    /// </summary>
    ~DirectorySelectionViewModel()
    {
      Dispose(false);
    }

    #endregion

    #region properties

    /// <summary>
    /// Represents the selected directory.
    /// </summary>
    public IOViewModel SelectedDirectory
    {
      get { return _selectedDirectory; }
      set
      {
        if (value == _selectedDirectory) return;

        _selectedDirectory = value;
        HandlePropertyChanged();
      }
    }

    /// <summary>
    /// Represents the service used to retrieve directories.
    /// </summary>
    public IDirectoryService DirectoryService
    {
      get { return _directoryService; }
      set
      {
        if (value == _directoryService) return;

        _directoryService = value;
        // ReSharper disable once ExplicitCallerInfoArgument
        HandlePropertyChanged("RootDirectories");
        // ReSharper disable once ExplicitCallerInfoArgument
        HandlePropertyChanged("SelectedDirectory");
      }
    }

    /// <summary>
    /// Gets the root directories.
    /// </summary>
    public ObservableCollection<ITreeViewItemViewModel> RootDirectories
    {
      get
      {
        if (DirectoryService == null) return null;

        var result = new ObservableCollection<ITreeViewItemViewModel>();
        List<string> rootDirectories = DirectoryService.RootDirectories;
        foreach (string rootDirectory in rootDirectories)
        {
          var newDirectoryViewModel = new IOViewModel(rootDirectory, null, DirectoryService);
          result.Add(newDirectoryViewModel);
        }

        return result;
      }
    }

    /// <summary>
    /// Gets or sets whether the directories should be shown.
    /// </summary>
    public bool ShowDirectories
    {
      get { return _showDirectories; }
      set
      {
        _showDirectories = value;
        HandlePropertyChanged();
      }
    }

    /// <summary>
    /// Command used to select the directories.
    /// </summary>
    public ICommand SelectDirectoryCommand
    {
      get 
      {
        return 
          _selectDirectoryCommand ??
               (_selectDirectoryCommand =
                  new DelegateCommand(
                    SelectDirectoryCommandExecuted, 
                    CanExecuteSelectDirectoryCommand));
      }
    }

    #endregion

    #region methods

    /// <summary>
    /// Returns whether <see cref="SelectDirectoryCommand"/> can/may be executed.
    /// </summary>
    /// <returns></returns>
    protected bool CanExecuteSelectDirectoryCommand()
    {
      return true;
    }

    /// <summary>
    /// <see cref="SelectDirectoryCommand"/> should be executed.
    /// </summary>
    protected void SelectDirectoryCommandExecuted()
    {
      ShowDirectories = !ShowDirectories;
    }

    #endregion
  }
}
